package leetcode.editor.cn;

////你这个学期必须选修 numCourses 门课程，记为 0 到 numCourses - 1 。 
////
//// 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出，其中 prerequisites[i] = [ai, bi] 
//，表
////示如果要学习课程 ai 则 必须 先学习课程 bi 。 
////
//// 
//// 例如，先修课程对 [0, 1] 表示：想要学习课程 0 ，你需要先完成课程 1 。 
//// 
////
//// 请你判断是否可能完成所有课程的学习？如果可以，返回 true ；否则，返回 false 。 
////
//// 
////
//// 示例 1： 
////
//// 
////输入：numCourses = 2, prerequisites = [[1,0]]
////输出：true
////解释：总共有 2 门课程。学习课程 1 之前，你需要完成课程 0 。这是可能的。 
////
//// 示例 2： 
////
//// 
////输入：numCourses = 2, prerequisites = [[1,0],[0,1]]
////输出：false
////解释：总共有 2 门课程。学习课程 1 之前，你需要先完成课程 0 ；并且学习课程 0 之前，你还应先完成课程 1 。这是不可能的。 
////
//// 
////
//// 提示： 
////
//// 
//// 1 <= numCourses <= 10⁵ 
//// 0 <= prerequisites.length <= 5000 
//// prerequisites[i].length == 2 
//// 0 <= ai, bi < numCourses 
//// prerequisites[i] 中的所有课程对 互不相同 
//// 
//// Related Topics 深度优先搜索 广度优先搜索 图 拓扑排序 👍 1362 👎 0
//

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Java：【207】- 课程表
 */
public class LeetCode_207_CourseSchedule {
    public static void main(String[] args) {
        Solution solution = new LeetCode_207_CourseSchedule().new Solution();
        // TO TEST
        System.out.println(solution.canFinish(3, new int[][]{{1, 0}, {1, 2}, {0, 1}}));
    }

    //leetcode submit region begin(Prohibit modification and deletion)

    class Solution {
        public boolean canFinish(int numCourses, int[][] prerequisites) {
            List<Integer>[] map = new ArrayList[numCourses];
            int[] map2 = new int[numCourses]; // 0:未查 1:可以修 2:修不了
            for (int i = 0; i < numCourses; i++) {
                map[i] = new ArrayList<>();
            }
            for (int[] clazz : prerequisites) { // 构建图
                map[clazz[0]].add(clazz[1]);
            }
            for (int i = 0; i < numCourses; i++) {
                if (!finish(numCourses, map, map2, i, 1))
                    return false;
            }
            return true;
        }

        public boolean finish(int numCourses, List<Integer>[] map, int[] map2, int clazz, int count) {
            if (count > numCourses) return false;
            List<Integer> pres = map[clazz];  // clazz的先修课程
            for (int pre : pres) {
                if(map2[pre] ==1) continue; // 先修课程可以修
                if (map2[pre]==2 || !finish(numCourses, map, map2, pre, count+1)){ // 先修课程不可以修
                    map2[clazz] = 2;
                    return false;
                }
            }
            map2[clazz] = 1; //能到这说明clazz可以修
            return true;
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}